package com.ddone;

import com.ddone.bean.User;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.client.IndicesClient;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.PutMappingRequest;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.bucket.terms.ParsedStringTerms;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author ddone
 * @date 2024/4/9-19:01
 */
@SpringBootTest
public class EsHighLevelClientTest {

    @Resource
    private RestHighLevelClient esHighLevelClient;

    private final ObjectMapper MAPPER = new ObjectMapper();

    @Test
    public void testIndex() throws IOException {
        IndicesClient indicesClient = esHighLevelClient.indices();
        CreateIndexRequest goods = new CreateIndexRequest("goods");
        String mapping = "{\n" +
                "      \"properties\" : {\n" +
                "        \"address\" : {\n" +
                "          \"type\" : \"text\",\n" +
                "          \"analyzer\" : \"ik_max_word\"\n" +
                "        },\n" +
                "        \"age\" : {\n" +
                "          \"type\" : \"long\"\n" +
                "        },\n" +
                "        \"name\" : {\n" +
                "          \"type\" : \"keyword\"\n" +
                "        }\n" +
                "      }\n" +
                "    }";
        goods.mapping(mapping, XContentType.JSON);
        GetRequest getRequest = new GetRequest("goods", "id");
        boolean exists = esHighLevelClient.exists(getRequest, RequestOptions.DEFAULT);
        if (!exists) {
            CreateIndexResponse response = indicesClient.create(goods, RequestOptions.DEFAULT);
            System.out.println(response);
            System.out.println(response.isAcknowledged());
        }

    }

    @Test
    public void testIndex2() throws IOException {
        IndicesClient indicesClient = esHighLevelClient.indices();
        CreateIndexRequest goods = new CreateIndexRequest("goods");
        GetIndexRequest getRequest = new GetIndexRequest("goods");
        boolean exists = indicesClient.exists(getRequest, RequestOptions.DEFAULT);

        if(!exists){
            indicesClient.create(goods, RequestOptions.DEFAULT);
        }
        XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
        jsonBuilder.startObject();
        {
            jsonBuilder.startObject("properties");
            {
                jsonBuilder.startObject("name");
                {
                    jsonBuilder.field("type", "text");
                }
                jsonBuilder.endObject();
                jsonBuilder.startObject("age");
                {
                    jsonBuilder.field("type", "long");
                }
                jsonBuilder.endObject();
                jsonBuilder.startObject("address");
                {
                    jsonBuilder.field("type", "text");
                }
                jsonBuilder.endObject();
            }
            jsonBuilder.endObject();
        }
        jsonBuilder.endObject();
            PutMappingRequest putMappingRequest = new PutMappingRequest("goods");
            putMappingRequest.source(jsonBuilder);
            indicesClient.putMapping(putMappingRequest, RequestOptions.DEFAULT);
    }

    @Test
    public void testDelete() throws IOException {
        IndicesClient indicesClient = esHighLevelClient.indices();
        DeleteIndexRequest deleteIndexRequest = new DeleteIndexRequest("goods");
        AcknowledgedResponse response = indicesClient.delete(deleteIndexRequest, RequestOptions.DEFAULT);
        System.out.println(response.isAcknowledged());
    }

    @Test
    public void testSave() throws IOException {
        //数据对象，map
        Map<String,Object> data = new HashMap<>();
        data.put("address","中国上海");
        data.put("name","大西瓜");
        data.put("age",20L);
        data.put("price",35);

        //1.获取操作文档的对象
        IndexRequest request = new IndexRequest("goods").id("1").source(data);
        //添加数据，获取结果
        IndexResponse response = esHighLevelClient.index(request, RequestOptions.DEFAULT);

        //打印响应结果
        System.out.println(response.getId());
    }

    @Test
    public void testSaveObject() throws IOException {
        User user = User
                .builder()
                .name("王五")
                .age(20)
                .pwd("wangwu@126.com")
                .id(1L)
                .build();
        //1.获取操作文档的对象
        String userJson = MAPPER.writeValueAsString(user);
        IndexRequest request = new IndexRequest("user2").id("1").source(userJson,XContentType.JSON);
        //添加数据，获取结果
        IndexResponse response = esHighLevelClient.index(request, RequestOptions.DEFAULT);
    }

    @Test
    public void getById() throws IOException {
        // GetRequest getRequest = new GetRequest("goods", "1");
        GetRequest getRequest = new GetRequest("goods").id("1");
        GetResponse response = esHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
        String sourceAsString = response.getSourceAsString();
        System.out.println(sourceAsString);
    }

    @Test
    public void deleteById() throws IOException {
        DeleteRequest deleteRequest = new DeleteRequest("goods", "1");
        DeleteResponse response = esHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
        System.out.println(response);

    }

    @Test
    public void testRestHighLevelClient() throws IOException {
        //搜索条件构建器
        SearchSourceBuilder builder = new SearchSourceBuilder();
        // 构建搜索请求体，设置索引库 并设置搜索条件构建器
        SearchRequest searchRequest = new SearchRequest(new String[]{"user"}, builder);
        BoolQueryBuilder boolQuery = QueryBuilders.boolQuery();
        boolQuery.must(QueryBuilders.matchQuery("name", "鹏"));
        boolQuery.filter(QueryBuilders.rangeQuery("age").gte(20).lte(100));
        builder.query(boolQuery);
        builder.sort("age", SortOrder.DESC);
        // 分页
        builder.from(2);
        builder.size(10);

        // 高亮
        builder.highlighter(new HighlightBuilder().field("name").preTags("<em>").postTags("</em>"));

        // 聚合
        builder.aggregation(AggregationBuilders.terms("pwdAgg").field("password"));

        System.out.println(builder);
        SearchResponse response = esHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println(response);
        SearchHits hits = response.getHits();
        System.out.println("一共命中：" + hits.getTotalHits());
        SearchHit[] hitsHits = hits.getHits();
        for (SearchHit hitsHit : hitsHits) {
            String json = hitsHit.getSourceAsString();
            User user = MAPPER.readValue(json, User.class);
            System.out.println("高亮前：" + user);

            // 高亮结果集
            Map<String, HighlightField> highlightFields = hitsHit.getHighlightFields();
            HighlightField highlightField = highlightFields.get("name");
            user.setName(highlightField.fragments()[0].string());
            System.out.println("高亮后：" + user);
        }

        // 聚合结果集
        Aggregations aggregations = response.getAggregations();
        ParsedStringTerms pwdAgg = aggregations.get("pwdAgg");
        List<? extends Terms.Bucket> buckets = pwdAgg.getBuckets();
        buckets.forEach(bucket -> {
            System.out.println("桶的key：" + bucket.getKeyAsString());
            System.out.println("桶中的元素数量：" + bucket.getDocCount());
        });
    }
}
